from typing import Optional, List
from sqlalchemy import (
    Column,
    Integer,
    String,
    Float,
    DateTime,
    ForeignKey,
    Table,
    Boolean,
    Text,
)
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship, Mapped, mapped_column
import datetime
import warnings
from .base import Base, default_now

warnings.filterwarnings("ignore", category=DeprecationWarning)

################################################
###########       MANAGEMENT       #############
################################################


class LogicalRepository(Base):
    """
    逻辑仓库
    
    id 主键
    key 仓库唯一标识
    name 仓库名称
    created_at 创建时间
    updated_at 更新时间
    """
    
    __tablename__ = "logical_repositories"

    id: Mapped[int] = mapped_column(primary_key=True, index=True, autoincrement=True)
    key: Mapped[str] = mapped_column(String(8), index=True, unique=True, nullable=False)
    name: Mapped[str] = mapped_column(String(100), nullable=False)
    created_at: Mapped[datetime.datetime] = mapped_column(DateTime, default=default_now)
    updated_at: Mapped[datetime.datetime] = mapped_column(DateTime, default=default_now, onupdate=default_now)

    # 关系
    logical_entries: Mapped[List["LogicalEntry"]] = relationship(secondary="relation_repo_entry", back_populates="repositories")
    
    @hybrid_property
    def repo_key(self) -> str:
        return self.key


class LogicalEntry(Base):
    """
    逻辑条目
    
    id 主键
    key 条目唯一标识
    path 条目路径
    """
    __tablename__ = "logical_entries"

    id: Mapped[int] = mapped_column(primary_key=True, index=True, autoincrement=True)
    key: Mapped[str] = mapped_column(String(16), index=True, unique=True, nullable=False)
    path: Mapped[Optional[str]] = mapped_column(Text, nullable=False)  # 当前版本
    is_directory: Mapped[bool] = mapped_column(Boolean, default=False)  # 是否是目录
    parent_id: Mapped[Optional[int]] = mapped_column(ForeignKey("logical_entries.id"), nullable=True)  # 父目录ID

    @hybrid_property
    def entry_name(self) -> Optional[str]:
        return self.path.split("/")[-1] if self.path else None

    @hybrid_property
    def entry_key(self) -> str:
        return self.key

    @hybrid_property
    def is_dir(self) -> bool:
        return self.is_directory
    
    @hybrid_property
    def file_key(self) -> str | None:
        return self.file.key if isinstance(self.file, LogicalFile) else None

    # 关系
    parent: Mapped[Optional["LogicalEntry"]] = relationship("LogicalEntry", remote_side=[id], backref="children", cascade="all, delete")
    repositories: Mapped["LogicalRepository"] = relationship(secondary="relation_repo_entry", back_populates="logical_entries")
    file: Mapped["LogicalFile"] = relationship(secondary="relation_entry_file", back_populates="entries")


class LogicalFile(Base):
    __tablename__ = "logical_files"

    id: Mapped[int] = mapped_column(primary_key=True, index=True, autoincrement=True)
    key: Mapped[str] = mapped_column(String(8), index=True, unique=True, nullable=False)
    name: Mapped[str] = mapped_column(String(100), nullable=False)
    created_at: Mapped[datetime.datetime] = mapped_column(DateTime, default=default_now)
    updated_at: Mapped[datetime.datetime] = mapped_column(DateTime, default=default_now, onupdate=default_now)

    # 关系
    top_version: Mapped[Optional["LogicalVersion"]] = relationship(
        "LogicalVersion",
        secondary="relation_file_version",
        primaryjoin="and_(LogicalFile.key==RelationFileVersion.file_key, RelationFileVersion.is_top==True)",
        uselist=False,
        viewonly=True,
    )
    versions: Mapped[List["LogicalVersion"]] = relationship(secondary="relation_file_version", back_populates="logical_file")
    entries: Mapped[List["LogicalEntry"]] = relationship(secondary="relation_entry_file", back_populates="file")

    @hybrid_property
    def file_key(self) -> str:
        return self.key


class LogicalVersion(Base):
    """
    逻辑文件版本
    
    id 主键
    key 版本唯一标识
    version_number 版本号
    created_at 创建时间
    """
    __tablename__ = "logical_versions"

    id: Mapped[int] = mapped_column(primary_key=True, index=True, autoincrement=True)
    key: Mapped[str] = mapped_column(String(8), index=True, unique=True, nullable=False)
    created_at: Mapped[datetime.datetime] = mapped_column(DateTime, default=default_now)

    @hybrid_property
    def version_code(self) -> str:
        return self.created_at.strftime("%Y%m%d%H%M%S") + self.key

    @hybrid_property
    def version_key(self) -> str:
        return self.key
    
    # 关系
    logical_file: Mapped["LogicalFile"] = relationship(secondary="relation_file_version", back_populates="versions")

class RelationRepoEntry(Base):
    """
    仓库-条目关联表
    
    repository_key 仓库key
    entry_key 条目key
    """
    __tablename__ = "relation_repo_entry"
    
    repository_key: Mapped[str] = mapped_column(String(8), ForeignKey("logical_repositories.key"), primary_key=True)
    entry_key: Mapped[str] = mapped_column(String(16), ForeignKey("logical_entries.key"), primary_key=True)


class RelationEntryFile(Base):
    """条目-文件关联表"""
    __tablename__ = "relation_entry_file"
    
    entry_key: Mapped[str] = mapped_column(String(16), ForeignKey("logical_entries.key"), primary_key=True)
    file_key: Mapped[str] = mapped_column(String(8), ForeignKey("logical_files.key"), primary_key=True)


class RelationFileVersion(Base):
    """
    文件-版本关联表
    
    file_key 文件key
    version_key 版本key
    is_top 是否是置顶版本
    """
    __tablename__ = "relation_file_version"
    
    file_key: Mapped[str] = mapped_column(String(8), ForeignKey("logical_files.key"), primary_key=True)
    version_key: Mapped[str] = mapped_column(String(8), ForeignKey("logical_versions.key"), primary_key=True)
    is_top: Mapped[bool] = mapped_column(Boolean, default=False)  # 是否是置顶版本